using System.Collections.Generic;
using System.Linq;
using Nop.Core.Caching;
using Nop.Core.Data;
using Nop.Core.Domain.Directory;
using Nop.Services.Events;

namespace Nop.Services.Directory
{
    /// <summary>
    /// District service
    /// </summary>
    public class DistrictService : IDistrictService
    {
        #region Constants

        private const string DISTRICTS_ALL_KEY = "Nop.district.all-{0}";
        private const string DISTRICTS_BILLING_KEY = "Nop.district.billing-{0}";
        private const string DISTRICTS_SHIPPING_KEY = "Nop.district.shipping-{0}";
        private const string DISTRICTS_BY_ID_KEY = "Nop.district.id-{0}";
        private const string DISTRICTS_PATTERN_KEY = "Nop.district.";

        #endregion

        #region Fields

        private readonly IRepository<District> _districtRepository;
        private readonly IEventPublisher _eventPublisher;
        private readonly ICacheManager _cacheManager;

        #endregion

        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="cacheManager">Cache manager</param>
        /// <param name="districtRepository">Country repository</param>
        /// <param name="eventPublisher">Event published</param>
        public DistrictService(ICacheManager cacheManager,
                               IRepository<District> districtRepository,
                               IEventPublisher eventPublisher)
        {
            _cacheManager = cacheManager;
            _districtRepository = districtRepository;
            _eventPublisher = eventPublisher;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Gets all countries that allow shipping
        /// </summary>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>Country collection</returns>
        public virtual IList<District> GetAllDistrictsForShipping(bool showHidden = false)
        {
            string key = string.Format(DISTRICTS_SHIPPING_KEY, showHidden);
            return _cacheManager.Get(key, () =>
                                              {
                                                  var query = from c in _districtRepository.Table
                                                              orderby c.DisplayOrder , c.Name
                                                              where (showHidden || c.Published) && c.AllowsShipping
                                                              select c;
                                                  var countries = query.ToList();
                                                  return countries;
                                              });
        }

        /// <summary>
        /// Gets a districts collection by state/province identifier
        /// </summary>
        /// <param name="stateProvinceId">State/Province identifier</param>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>District collection</returns>
        public virtual IList<District> GetDistrictsByStateProvinceId(int stateProvinceId, bool showHidden = false)
        {
            string key = string.Format(DISTRICTS_ALL_KEY, stateProvinceId);
            return _cacheManager.Get(key, () =>
            {
                var query = from district in _districtRepository.Table
                            orderby district.DisplayOrder
                            where district.StateProvinceId == stateProvinceId &&
                            (showHidden || district.Published)
                            select district;
                var districts = query.ToList();
                return districts;
            });
        }

        #endregion
    }
}